package com.example.kotlindemo.demo

/**
 * Author 87231
 * 2022/8/28 22:30
 *
 * Unit9
 * describe：数据类与封装类
 * 一、数据类型
 * 二、密封类
 **/
class Unit9 {
    /**
     * 一、数据类
     * kotlin可以创建一个包含数据的类，关键字是date
     * data class User(val name:String,val age:Int)
     * 编译器还会自动的从主构造函数中个根据所声明的属性提取以下函数：
     * 1.equals()/hashCode()
     * 2.toString 格式如 "User(name = tom,age =12)"
     * 3.componentN() functions对应于属性，按声明顺序排列
     * 4.copy() 函数
     * 如果这些函数已经被明确定义了，或者从超类中继承而来，就不会再生成
     * 为了保证代码的一致性以及有意义，数据类型需要满足以下条件：
     * 1）主构造函数至少包含一个参数
     * 2）所有的主构造函数的参数必须标识为val或者var
     * 3）数据类不可声明为abstract，open，sealed或者inner
     * 4）数据类型不能继承其他类（但是可以实现接口）
     */
    data class User(val name: String, val age: Int)

    /**
     * 数据类型以及解构声明
     * 组件函数允许数据类在解构声明中使用
     */
    fun testA(){
        var user = User(name = "zhan", age = 12)
        var (name,age) = user
        println("$name is $age years old!")
    }
    /**
     * 二、密封类
     *1. 密封类用来标识受限制的类继承解构：当一个值为有限几种的类型，而不能有任何其他类型时。
     * 在某种意义上，他们是枚举类的扩展：枚举类型的值集合也是受限的，但每个枚举常量只存在一个实例，
     * 二密封类的一个子类可以有可包含状态的多个实例。
     * 声明一个密封类，使用sealed修饰类，密封类可以有子类，但是所有的子类都必须嵌套在密封类中。
     * sealed不能修饰interface，abstract，class（会报warning，但是不会出现编译错误）
     *
     */
    sealed class Test{
        data class DataA(val name: String,val age: Int): Test()
        data class DataB(val id:Int,val height:Double):Test()
        object DataC :Test()

    }
    fun test(expr: Test): String = when(expr) {
        is Test.DataA -> "DataA"
        is Test.DataB -> "DataB"
        Test.DataC -> "DataC"
        // 不再需要 `else` 子句，因为我们已经覆盖了所有的情况
    }




}